<?php

/**
 * @link https://www.humhub.org/
 * @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
 * @license https://www.humhub.com/licences
 */

#namespace humhub\modules\content\components\actions;
namespace humhub\modules\api\cccstream;

use humhub\modules\space\models\Membership;
use Yii;
use humhub\modules\content\models\Content;
use humhub\modules\content\models\WallEntry;
use humhub\modules\user\models\User;
use yii\base\ActionEvent;
use yii\base\Exception;
use humhub\modules\space\models\Space;
use humhub\modules\content\components\ContentContainerController;
#Task
use humhub\modules\api\models\TaskUser;

/**
 * BaseStreamAction
 *
 * @author luke
 * @since 0.11
 */
class Stream extends \yii\base\Action
{
    /**
     * @event ActionEvent Event triggered before this action is run.
     * This can be used for example to customize [[activeQuery]] before it gets executed.
     * @since 1.1.1
     */
    const EVENT_BEFORE_RUN = 'beforeRun';
    /**
     * @event ActionEvent Event triggered after this action is run.
     * @since 1.1.1
     */
    const EVENT_AFTER_RUN = 'afterRun';


    /**
     * Constants used for sorting
     */
    const SORT_CREATED_AT = 'c';
    const SORT_UPDATED_AT = 'u';

    /**
     * Modes
     */
    const MODE_NORMAL = "normal";
    const MODE_ACTIVITY = "activity";

    /**
     * Maximum wall entries per request
     */
    const MAX_LIMIT = 50;

    /**
     * @var string
     */
    public $mode;

    /**
     * First wall entry id to deliver
     *
     * @var int
     */
    public $from;

    /**
     * Sorting Mode
     *
     * @var int
     */
    public $sort;

    /**
     * Maximum wall entries to return
     * @var int
     */
    public $limit = 20;

    /**
     * Filters
     *
     * @var array
     */
    public $filters = [];

    /**
     * @var \yii\db\ActiveQuery
     */
    public $activeQuery;

    /**
     * Optional stream user
     * if no user is specified, the current logged in user will be used.
     *
     * @var User
     */
    public $user;

    public function init()
    {
        $this->activeQuery = WallEntry::find();

        // If no user is set, take current if logged in
        if ($this->user === null && !Yii::$app->user->isGuest) {
            $this->user = Yii::$app->user->getIdentity();
        }


        // Read parameters
        if (!Yii::$app->request->isConsoleRequest) {
            $from = Yii::$app->getRequest()->get('from', 0);
            if ($from != 0) {
                $this->from = (int) $from;
            }

            /**
             * Sorting
             */
            $sort = Yii::$app->getRequest()->get('sort', Yii::$app->getModule('content')->settings->get('stream.defaultSort'));
            if ($sort === static::SORT_CREATED_AT || $sort === static::SORT_UPDATED_AT) {
                $this->sort = $sort;
            } else {
                $this->sort = static::SORT_CREATED_AT;
            }

            $limit = Yii::$app->getRequest()->get('limit', '');
            if ($limit != "" && $limit <= self::MAX_LIMIT) {
                $this->limit = $limit;
            }
            $mode = Yii::$app->getRequest()->get('mode', '');
            if ($mode != "" && ($mode == self::MODE_ACTIVITY || $mode == self::MODE_NORMAL)) {
                $this->mode = $mode;
            }
            foreach (explode(',', Yii::$app->getRequest()->get('filters', "")) as $filter) {
                $this->filters[] = trim($filter);
            }
        }

        $this->setupCriteria();
        $this->setupFilters();
    }

    public function setupCriteria()
    {
        $this->activeQuery->joinWith('content');
        $this->activeQuery->joinWith('content.createdBy');
        $this->activeQuery->joinWith('content.contentContainer');

        $this->activeQuery->limit($this->limit);
        $this->activeQuery->andWhere(['user.status' => User::STATUS_ENABLED]);

        /**
         * Handle Stream Mode (Normal Stream or Activity Stream)
         */
        if ($this->mode == self::MODE_ACTIVITY) {
            $this->activeQuery->andWhere(['content.object_model' => \humhub\modules\activity\models\Activity::className()]);

            // Dont show own activities
            if ($this->user !== null) {
                $this->activeQuery->leftJoin('activity', 'content.object_id=activity.id AND content.object_model=:activityModel', ['activityModel' => \humhub\modules\activity\models\Activity::className()]);
                $this->activeQuery->andWhere('content.created_by != :userId', array(':userId' => $this->user->id));
            }
        } else {
            $this->activeQuery->andWhere(['!=', 'content.object_model', \humhub\modules\activity\models\Activity::className()]);
        }

        /**
         * Setup Sorting
         */
        if ($this->sort == self::SORT_UPDATED_AT) {
            $this->activeQuery->orderBy('wall_entry.updated_at DESC');
            if ($this->from != "")
                $this->activeQuery->andWhere("wall_entry.updated_at < (SELECT updated_at FROM wall_entry wd WHERE wd.id=" . $this->from . ")");
        } else {
            $this->activeQuery->orderBy('wall_entry.id DESC');
            if ($this->from != "")
                $this->activeQuery->andWhere("wall_entry.id < " . $this->from);
        }
    }

    /**
     * Setup additional filters
     */
    public function setupFilters()
    {
        if (in_array('entry_files', $this->filters)) {
            $fileSelector = (new \yii\db\Query())
                    ->select(["id"])
                    ->from('file')
                    ->where('file.object_model=content.object_model AND file.object_id=content.object_id')
                    ->limit(1);
            $fileSelectorSql = Yii::$app->db->getQueryBuilder()->build($fileSelector)[0];

            $this->activeQuery->andWhere('(' . $fileSelectorSql . ') IS NOT NULL');
        }

        // Setup Post specific filters
        // Task +++
        //if (in_array('posts_links', $this->filters)) {
        //    $this->activeQuery->leftJoin('post', 'content.object_id=post.id AND content.object_model=:postModel', ['postModel' => \humhub\modules\post\models\Post::className()]);
        //    $this->activeQuery->andWhere("post.url is not null");
        //}
        /*
        $post_on = '';
        $post_data = [];
        if (in_array('posts_links', $this->filters)) {
            $post_on .= ' content.object_id=post.id AND content.object_model=:postModel ';
            $post_data['postModel'] = \humhub\modules\post\models\Post::className();
            $this->activeQuery->andWhere("post.url is not null");
        }
        $p_type = \Yii::$app->request->get('p_type');
        if( in_array($p_type, array('0','1','2','3'))){
            $link = $post_on?'AND':'';
            $post_on .= ' '. $link .' post.p_type=' .$p_type. ' ';
        }
        if( $post_on ){
            if( $post_data ){
                $this->activeQuery->leftJoin('post', $post_on, $post_data);
            }else{
                $this->activeQuery->leftJoin('post', $post_on);
            }
        }
        */
        $post_join = 0;
        if (in_array('posts_links', $this->filters)) {
            $post_join = 1;
            $this->activeQuery->andWhere("post.url is not null");
        }
        $p_type = \Yii::$app->request->get('p_type');
        //全部数据 不含八卦数据
        if ($p_type==''){
            $p_type=[0,1,2,3];
        }
        if( in_array($p_type, array('0','1','2','3','4'))){
            $post_join = 1;
            $this->activeQuery->andWhere("post.p_type=$p_type");
        }
        //全部数据 不含八卦数据
        if (is_array($p_type) ){
            $post_join = 1;
            $this->activeQuery->andWhere(['in','post.p_type',$p_type]);
        }
        if( $post_join ){
            $this->activeQuery->leftJoin('post', 'content.object_id=post.id AND content.object_model=:postModel', ['postModel' => \humhub\modules\post\models\Post::className()]);
        }
      
        // Only apply archived filter when we should load more than one entry
        if ($this->limit != 1) {
            if (!in_array('entry_archived', $this->filters)) {
                $this->activeQuery->andWhere("(content.archived != 1 OR content.archived IS NULL)");
            }
        }
        // Show only mine items
        if (in_array('entry_mine', $this->filters) && $this->user !== null) {
            $this->activeQuery->andWhere(['content.created_by' => $this->user->id]);
        }
        // Show only items where the current user is involed
        if (in_array('entry_userinvoled', $this->filters) && $this->user !== null) {

            $this->activeQuery->leftJoin('user_follow', 'content.object_model=user_follow.object_model AND content.object_id=user_follow.object_id AND user_follow.user_id = :userId', ['userId' => $this->user->id]);
            $this->activeQuery->andWhere("user_follow.id IS NOT NULL");
        }
        if (in_array('model_posts', $this->filters)) {
            $this->activeQuery->andWhere(["content.object_model" => \humhub\modules\post\models\Post::className()]);
        }
        // Visibility filters
        if (in_array('visibility_private', $this->filters)) {
            $this->activeQuery->andWhere(['content.visibility' => Content::VISIBILITY_PRIVATE]);
        }
        if (in_array('visibility_public', $this->filters)) {
            $this->activeQuery->andWhere(['content.visibility' => Content::VISIBILITY_PUBLIC]);
        }
    }

    public function getWallEntries()
    {
        //if(isset($_GET['xx']) && $_GET['xx']==1){ echo $this->activeQuery->createCommand()->getRawSql();exit; }
        return $this->activeQuery->all();
    }

    public function run()
    {
        Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;

        $wallEntries = $this->getWallEntries();
        $is_ad_Query = clone $this->activeQuery;
        //echo $this->is_ad_Query->createCommand()->getRawSql();exit;
        $is_ad_sql = $is_ad_Query->createCommand()->getRawSql();
        if( strpos($is_ad_sql, 'wall_entry.id < '.$this->from) > 1 ){
            $is_ad_sql = str_replace('wall_entry.id < '.$this->from, 'wall_entry.id > '.$this->from, $is_ad_sql);
            $is_ad_sql = substr($is_ad_sql, 0, strpos($is_ad_sql, 'ORDER BY'));
            $is_ad_sql = str_replace('SELECT `wall_entry`.*', 'SELECT count(*)', $is_ad_sql);
            $ad_count = Yii::$app->db->createCommand($is_ad_sql)->queryScalar();
            if( $ad_count ){
                $ad_page = ceil($ad_count / $this->limit) + 1;
            }
        }else{
            $ad_page = 1;
        }

        $output = "";
        $generatedWallEntryIds = [];
        $lastEntryId = "";
        $wallList = Array();
        $wallOne = Array();
        $is_ad = isset($_GET['is_ad'])?$_GET['is_ad']:0; //来自首页

        foreach ($wallEntries as $key=>$wallEntry) {
            //首页置顶
            if( $this->from=='' && $is_ad==1 && $key==0 ){
                $ad_data = \humhub\modules\api\models\TopList::getList(2);

                if(!empty($ad_data['list'])){
                    if( count($ad_data) ){
                        $ad['ad']     = $ad_data;
                        $ad['object'] = ['p_type' => -11];
                        $wallList[] = $ad;
                    }
                }

            }
            if( $is_ad==1 && $key==3 ){
                $ad_data = \humhub\modules\api\models\TopList::getList(3, $ad_page);

                if(!empty($ad_data['list'])){
                    if( count($ad_data) ){
                        $ad['ad']     = $ad_data;
                        $ad['object'] = ['p_type' => -10];
                        $wallList[] = $ad;
                    }
                }

            }

            $underlyingObject = $wallEntry->content->getPolymorphicRelation();

            if ($underlyingObject === null) {
                throw new Exception('Could not get contents underlying object!');
            }

            $underlyingObject->populateRelation('content', $wallEntry->content);

            //$output .= $this->controller->renderAjax('@humhub/modules/content/views/layouts/wallEntry', [
            //    'entry' => $wallEntry,
            //    'user' => $underlyingObject->content->user,
            //    'mode' => $this->mode,
            //    'object' => $underlyingObject,
            //    'content' => $underlyingObject->getWallOut()
            //        ], true);
            //EX: getWallOut: content/components/CAR::
            //    -- x = new:: humhub\modules\post\widgets\WallEntry
            //    -- x.contentObject = $this(post...)
            //    -- return x.renderWallEntry(content/widgets/WallEntry.php)
            //    ---- content/widgets/views/wallEntry.php
            //         show post
            //    ---- content\widgets\WallEntryAddons extends BaseStack
            //         show comment + like
            //    BaseStack::run->foreach:
            //    i=2 like ~like\widgets\LikeLink 
            //             ~content\widgets\WallEntryLinks 
            //    i=3 comment ~comment\widgets\Comments 

            $_user = $underlyingObject->content->user;
            $user['guid']  = $_user->guid;
            $user['image'] = $_user->getProfileImage()->getUrl();
            $user['displayname'] = $_user->displayName;
            $user['title'] = $_user->profile->title;
            $user['u_v']   = $_user->u_v;
            $user['g_name']   = $_user->g_name;
            $user['g_url']   = $_user->g_url;

            //<!-- show profile name -->
            //if (!Yii::$app->controller instanceof ContentContainerController && $container instanceof User && $container->id != $user->id){
            //    $container->displayName;
            //}

            //<!-- show space name -->
            $space = [];
            if (!Yii::$app->controller instanceof ContentContainerController && $underlyingObject->content->container instanceof Space){
                $_space = $underlyingObject->content->container;
                $space['name'] = $_space->name;
                //$space['img']  = $_space->getProfileImage()->getUrl();
                $space['guid'] = $_space->guid;
                $space['sid'] = $_space->id;
                //Task
                $space['tags']   = \humhub\widgets\RichText::widget(['text' => $_space->tags, 'record' => $_space]);
                $space['s_type'] = $_space->s_type;
                $space['s_special'] = $_space->s_special;
                $space['s_t1']   = $_space->s_t1;
                $space['s_t2']   = $_space->s_t2;
                $space['s_img']  = '';
                $_file = \humhub\modules\file\models\File::findOne(['guid' => $_space->s_img]);
                if( $_file ){
                    if ($_file->getMimeBaseType() == "image"){
                        $space['s_img']  = $_file->getPreviewImageUrl(400, 400);
                    }
                }
                //Task Users  提交作业统计
                //$tuser_where = ['space_id'=>$_space->id];
//                $tuser_where = ['task_id'=>$underlyingObject->id];
//                $tcount= TaskUser::find()->where($tuser_where)->count();
//                $space['usercount'] = $tcount;
//                $tuser = TaskUser::find()->select(['leader', 'user_id',])->where($tuser_where)
//                    ->with('user')->orderBy('leader DESC')->limit(6)->all();
//                $space['users'] = Array();
//                foreach($tuser AS $one){
//                    $u['user_id']      = $one->user_id;
//                    $u['leader']       = $one->leader;
//                    $u['guid']         = $one->user->guid;
//                    $u['username']     = $one->user->username;
//                    $u['profileimage'] = $one->user->getProfileImage()->getUrl();
//                    $u['displayname']  = $one->user->displayName;
//                    $space['users'][] = $u;
//                }
                //Task Users  参加任务统计
                $members=Membership::getSpaceMembersQuery($_space);
                $tcount=$members->count();
                $space['usercount'] = $tcount-1;
                $tuser=$members->andWhere(['group_id'=>'member'])->limit(6)->all();
                foreach($tuser AS $one){
                    $u['user_id']      = $one->id;
//                    $u['leader']       = 0;
                    $u['guid']         = $one->guid;
                    $u['username']     = $one->username;
                    $u['profileimage'] = $one->getProfileImage()->getUrl();
                    $u['displayname']  = $one->displayName;
                    $space['users'][] = $u;
                }

                //member
                $space['ismember'] = 0;
                if ($_space->isMember()) {
                    $space['ismember'] = 1;
                }
            }

            //Public Provate \humhub\modules\content\widgets\WallEntryLabels::widget(['object' => $object]);
            if ($underlyingObject->content->isSticked()){
                $o['label'] = 'Sticked';
            }
            if ($underlyingObject->content->isArchived()){
                $o['label'] = 'Archived';
            }
            if ($underlyingObject->content->isPublic()){
                $o['label'] = 'Public';
            }

            //content
            if (!$underlyingObject instanceof \humhub\modules\post\models\Post){
                $o['contentname'] = $underlyingObject->getContentName();
            }
            $o['id'] = $underlyingObject->id;
            //$o['message'] = $underlyingObject->getWallOut();
            //$o['message'] = $underlyingObject->message;
            $o['message'] = \humhub\widgets\RichText::widget(['text' => $underlyingObject->message, 'record' => $underlyingObject]);
            //去除< /br>
            $o['message'] = str_replace('<br />','',$o['message']);
            $o['created_at'] = $underlyingObject->created_at;
            $o['updated_at'] = $underlyingObject->updated_at;
            //Task
            $o['p_type'] = $underlyingObject->p_type;
            $o['p_team'] = $underlyingObject->p_team;
            $o['p_title'] = $underlyingObject->p_title;
            if ( $underlyingObject->p_type == '11' ){
                $o['p_title']= '';
            }else{
                $o['p_title']= \humhub\widgets\RichText::widget(['text' => $underlyingObject->p_title, 'record' => $underlyingObject]);
            }
            //Video
            //$o['p_video']= $underlyingObject->p_video;
            $o['p_video'] = '';
            $_video = \humhub\modules\file\models\File::findOne(['guid' => $underlyingObject->p_video]);
            if( $_video ){ $o['p_video'] = $_video->getUrl(); }
            $o['p_secs'] = $underlyingObject->p_secs;

            //Files
            if ($underlyingObject->isNewRecord && $underlyingObject->getRelation('content', false) !== null) {
                $files = \humhub\modules\file\models\File::findAll(['guid' => array_map('trim', explode(',', $underlyingObject->content->attachFileGuidsAfterSave))]);
            } else {
                $files = \humhub\modules\file\models\File::getFilesOfObject($underlyingObject);
            }
            $image = [];
            foreach ($files as $file){
                if ($file->getMimeBaseType() == "image"){
                    $image[] = $file->getPreviewImageUrl(400, 400);
                }
            }
            $image = array_reverse($image);
            $o['image'] = $image;

            $o['files'] = [];
            foreach ($files as $file){
                if ($file->getMimeBaseType() == "image")
                    continue;
                $f['url'] = $file->getUrl();
                $f['name'] = $file->file_name;
                $f['size'] = $file->size; //Yii::$app->formatter->asSize($file->size);
                $o['files'][] = $f;
            }

            //Comment
            //$o['comment'] = \humhub\modules\content\widgets\WallEntryAddons::widget(['object' => $underlyingObject]);
            //$o['comment'] = \humhub\modules\comment\widgets\Comments::widget(['object' => $underlyingObject]);
            $o['comment'] = \humhub\modules\api\cccstream\Comments::getLists($underlyingObject);

            //Like
            $o['like']    = \humhub\modules\api\cccstream\LikeLink::getLists($underlyingObject);

            //课程附加一个小节的视频 & 讲师
            if ( $underlyingObject->p_type == '2' ){
                //$episode = \humhub\modules\api\models\CourseEpisode::findOne(['season_id' => $underlyingObject->id]);
                //print_r($episode);exit;
                //if( $episode ){
                    $e['title']   = $underlyingObject->p_title; //$episode['title'];
                    $e['message'] = $underlyingObject->message; //$episode['message'];
                    $e['secs']    = $underlyingObject->p_secs;  //$episode['secs'];
                    $img = '';
                    $p_guid = md5('POST:'.$underlyingObject->id);
                    //$file = \humhub\modules\file\models\File::findOne(['guid' => $episode['imgguid']]);
                    $file = \humhub\modules\file\models\File::findOne(['guid' => $p_guid]);
                    if( $file ){
                        if ($file->getMimeBaseType() == "image"){
                            //$img = $file->getPreviewImageUrl(200, 200);
                            $img = $file->getUrl();
                        }
                    }
                    $e['image'] = $img;
                    //$e['video']   = $episode['video'];
                    $e['video'] = '';
                    $_video = \humhub\modules\file\models\File::findOne(['guid' => $underlyingObject->p_video]);
                    if( $_video ){ $e['video'] = $_video->getUrl(); }
                    $o['episodes'] = $e;

                    //讲师
                    //$t = json_decode($episode['teachers'], true);
                    $t = json_decode($underlyingObject->p_teachers, true);
                    if( isset( $t[0]) ){
                        $o['teachers'] = $t[0];
                    }else{
                        $o['teachers'] = (object)[];
                    }
                //}else{
                //    $o['episodes'] = (object)[];
                //    $o['teachers'] = (object)[];
                //}
            }
            //如果是任务分享的结果，附加每一个任务结果
            $o['jobs'] = [];
            if ( $underlyingObject->p_type == '11' ){
                $o['p_postid'] = $underlyingObject->p_postid;
                $o['jobs'] = \humhub\modules\api\models\TaskJob::getJobs($underlyingObject->p_postid, $underlyingObject->p_title);
            }

            //$wallOne['entry']  = $wallEntry; //table:wall_entry
            $wallOne['mode']  = $this->mode;
            $wallOne['user']  = $user;
            $wallOne['space'] = ($space)?$space:(object)$space;
            $wallOne['object'] = $o;
            $wallOne['wallEntry'] = $wallEntry->id;
            $wallList[] = $wallOne;

            $generatedWallEntryIds[] = $wallEntry->id;
            $lastEntryId = $wallEntry->id;
        }

        return [
            //'output' => $output,
            'output' => $wallList,
            'lastEntryId' => $lastEntryId,
            'counter' => count($wallEntries),
            'times'   => time(),
            'entryIds' => $generatedWallEntryIds
        ];
    }

    /**
     * This method is called right before `run()` is executed.
     * You may override this method to do preparation work for the action run.
     * If the method returns false, it will cancel the action.
     *
     * @return boolean whether to run the action.
     */
    protected function beforeRun()
    {
        $event = new ActionEvent($this);
        $this->trigger(self::EVENT_BEFORE_RUN, $event);
        return $event->isValid;
    }

    /**
     * This method is called right after `run()` is executed.
     * You may override this method to do post-processing work for the action run.
     */
    protected function afterRun()
    {
        $event = new ActionEvent($this);
        $this->trigger(self::EVENT_AFTER_RUN, $event);
    }
}
